package com.iocup.keybastion.utils;


import com.iocup.keybastion.authentication.AccessToken;
import com.iocup.keybastion.authentication.userdetails.UserDetails;
import com.iocup.keybastion.authorize.Authorizer;
import com.iocup.keybastion.context.SecurityContextHolder;
import com.iocup.keybastion.core.*;
import com.iocup.keybastion.annotion.Logical;
import com.iocup.keybastion.core.profile.CommonUserProfile;
import com.iocup.keybastion.core.profile.UserProfile;
import com.iocup.keybastion.core.session.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Optional;
import java.util.Set;

/**
 * 认证的工具类
 *
 * @author xyjxust
 * @create 2022/3/3 17:20
 **/
@Slf4j
public class AuthUtils {

    private static SecurityEngine securityEngine;


    public static void setSecurityEngine(SecurityEngine securityEngine) {
        AuthUtils.securityEngine = securityEngine;
    }

    public static SecurityLogicChecker getSecurityLogicChecker() {
        return securityEngine.getSecurityLogicChecker();
    }

    public static LoginLogic getLoginLogic() {
        return securityEngine.getLoginLogic();
    }

    public static LogoutLogic getLogoutLogic() {
        return securityEngine.getLogoutLogic();
    }

    public static Authorizer getAuthorizer() {
        return securityEngine.getAuthorizer();
    }

    /**
     * 判断是否登录成功
     *
     * @return
     */
    public static boolean isLogin() {
        if (securityEngine == null) {
            return false;
        }
        try {
            return securityEngine.getLoginLogic().isLogin();
        } catch (Exception e) {
            return false;
        }

    }

    public static String encodePassword(String password) {
        return securityEngine.getAuthenticationConfigurator()
                .getPasswordEncoder().encode(password);
    }

    public static boolean validatePassword(String srcPassword, String targetPassword) {
        return securityEngine.getAuthenticationConfigurator()
                .getPasswordVerifiers().verifiers(srcPassword, targetPassword);
    }

    /**
     * 登录接口
     */
    public static Object login(String authType, HttpActionAdapter actionAdapter) {
        return securityEngine.getLoginLogic().login(authType);
    }

    /**
     * 登录接口
     */
    public static Object login(String authType) {
        return securityEngine.getLoginLogic().login(authType);
    }

    /**
     * 登录接口
     */
    public static Object login() {
        return securityEngine.getLoginLogic().login(null);
    }

    public static void saveUserProfile(UserProfile userProfile) {
        securityEngine.getLoginLogic().saveUserProfile(userProfile);
    }

    /**
     * 登出
     *
     * @param loginName  登陆名字
     * @param clientName 登出客户端名字
     * @param device     设备名字：来自于那里
     */
    public static void logout(String loginName, String clientName, String device) {
        securityEngine.getLogoutLogic().logout(loginName, clientName, device);
    }

    /**
     * 登出
     */
    public static void logout() {
        if (isLogin()) {
            securityEngine.getLogoutLogic().logout(null, null, null);
        }
    }

    /**
     * 获取登录后的token信息
     *
     * @return
     */
    public static String getAccessToken() {
        return isLogin() ? SecurityContextHolder.getContext().getToken().getAccessToken() : null;
    }

    /**
     * 获取登录后的token信息
     *
     * @return
     */
    public static AccessToken getToken() {
        return isLogin() ? SecurityContextHolder.getContext().getToken() : null;
    }

    /**
     * 通过token获取用户信息
     *
     * @param token
     * @return
     */
    public static Optional<UserProfile> getUserProfile(String token) {
        Session session = securityEngine.getAuthenticationConfigurator().getTokenService().getByToken(token);
        return Optional.ofNullable(session == null ? null : session.getUserProfile());
    }

    /**
     * 通过token获取用户信息
     *
     * @param token
     * @return
     */
    public static Optional<Session> getSession(String token) {
        return Optional.ofNullable(securityEngine.getAuthenticationConfigurator().getTokenService().getByToken(token));
    }

    /**
     * 通过token获取用户信息
     *
     * @param id
     * @return
     */
    public static Optional<Session> getSessionById(String id) {
        return Optional.ofNullable(securityEngine.getAuthenticationConfigurator().getTokenService().getBySessionId(id));
    }


    /**
     * 获取登录的用户id
     *
     * @param <T>
     * @return
     */
    public static <T> T getUserId() {
        return isLogin() ? SecurityContextHolder.getContext().getUserProfile().getId() : null;
    }

    /**
     * 获取当前登录的用户登录名
     *
     * @return
     */
    public static String getLoginName() {
        return isLogin() ? SecurityContextHolder.getContext().getUserProfile().getLoginName() : null;
    }

    /**
     * 获取登录的用户信息
     *
     * @return
     */
    public static UserProfile getUserInfo() {
        return isLogin() ? SecurityContextHolder.getContext().getUserProfile() : null;
    }


    /**
     * 校验 role
     *
     * @param logical  模式
     * @param elements 需要具有的角色
     * @param roles    用户实际拥有的角色
     * @return 是否通过
     */
    public static boolean checkRoles(Logical logical, Set<String> elements, Set<String> roles) {
        return match(logical, elements, roles);
    }

    /**
     * 校验 permission
     *
     * @param logical     模式
     * @param elements    需要具有的权限
     * @param permissions 用户实际拥有的权限
     * @return 是否通过
     */
    public static boolean checkPermissions(Logical logical, Set<String> elements, Set<String> permissions) {
        return match(logical, elements, permissions);
    }

    /**
     * 验证
     *
     * @param elements    需要具有的
     * @param checkValues 实际拥有的
     * @return 是否通过
     */
    private static boolean match(Logical logical, Set<String> elements, Set<String> checkValues) {
        if (CollectionUtils.isEmpty(elements) || CollectionUtils.isEmpty(checkValues)) {
            return false;
        }
        if (logical == Logical.ANY) {
            for (String element : elements) {
                if (checkValues.contains(element)) {
                    return true;
                }
            }
            return false;
        }
        for (String element : elements) {
            if (!checkValues.contains(element)) {
                return false;
            }
        }
        return true;
    }

    public static UserProfile buildUserProfile(UserDetails userDetails) {
        return new CommonUserProfile().setId(userDetails.getId())
                .setLoginName(userDetails.getLoginName())
                .setUsername(userDetails.getUserName())
                .addPermissions(userDetails.getResources())
                .addRoles(userDetails.getRoles())
                .setAttribute(userDetails.getOthers());
    }
}
